﻿using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RayDen.RayEngine.Core;
using RayDen.RayEngine.Core.Devices;
using RayDen.RayEngine.Core.Interface;
using RayDen.RayEngine.Core.Threads;
using RayDen.RayEngine.Managers;
using RayDen.RayEngine.Samplers;

namespace RayDen.RayEngine.Engines.ProgressivePhotonMapping
{
    public class ProgressivePhotonMappingEngine : BaseRenderingEngine
    {
        private PPMContext context;

        private PPMEngineContext engineContext;

        public override int MaxThreadCount
        {
            get
            {
                return 1;
            }
        }

        public ProgressivePhotonMappingEngine(RayEngineScene scene)
            : base(scene)
        {
            engineContext = new PPMEngineContext();
        }

        public override bool PreprocessRequired
        {
            get
            {
                return true;
            }
        }

        public override void Preprocess(RayEngineScene scene, IntersectionEngine ie)
        {
            engineContext.BuildGatherPoints(ie, scene);
        }

        public override RenderThread CreateRenderThread(int threadIndex, IntersectionEngine intersectionDevice, RayEngineScene scene, IImageFilm film, IFrameManager frameManager, SamplingContext samplingContext)
        {
            if (context == null)
            {
                context = new PPMContext() { Width = film.Width, Height = film.Height};
                context.PhotonMapPhotons = film.Width * film.Height*4;
                context.MaxHitPoints = film.Width*film.Height*4;
            }

            return new PPMDeviceRenderThread(   threadIndex,
                                                intersectionDevice, 
                                                scene, LowLatencySampling,
                                                film, 
                                                samplingContext.PrimarySpaceSampler, (SurfaceSampler)samplingContext.SurfaceSampler, context, frameManager);
        }

        public override ISampler CreateSampler(int width, int height, int maxPathDepth, int threadIndex, int screenStartLine, int windowHeight)
        {
            var sampler = new RandomSampler() { lowLatency = LowLatencySampling, tIdx = threadIndex, screenStartLine = screenStartLine > 0 ? screenStartLine + 1 : screenStartLine, screenWidth = width, screenHeight = height };
            return sampler;
        }

        public override Core.Interface.IImageFilm CreateFilm(int width, int height)
        {
            return new PPMFilm(width,height) { engineContext = this.engineContext };
        }
    }
}
